import { CSSProperties, Ref, VNode } from 'vue'
import { RuleItem } from './rule'

export type WidgetType =
  | 'custom'
  | 'input'
  | 'textarea'
  | 'password'
  | 'number'
  | 'select'
  | 'checkbox'
  | 'radio'
  | 'rate'
  | 'slider'
  | 'switch'
  | 'cascader'
  | 'datePicker'
  | 'rangePicker'
  | 'timePicker'
  | 'treeSelect'
  | 'upload'

export interface OptionItem {
  value: string | number
  label: string
  disabled?: boolean
  key?: string
  title?: string
  isLeaf?: boolean
  children?: OptionItem[]
}

export interface TreeItem {
  value: string | number
  label: string
  children: TreeItem[]
  disabled?: boolean
  disableCheckbox?: boolean
  selectable?: boolean
  isLeaf?: boolean
}

export interface SlotRenders {
  [key: string]: Function
}

export interface UploadFile {
  uid: string
  name: string
  status: 'done' | 'uploading' | 'error' | 'removed'
  url?: string
}

export type SelectMode = 'multiple' | 'tags' | 'combobox'
export type DateMode = 'time' | 'date' | 'month' | 'year' | 'decade'

export interface WidgetOptions {
  type: WidgetType
  prop?: string
  label?: string
  rules?: RuleItem | RuleItem[]
  attrs?: {
    // util
    style?: CSSProperties
    id?: string
    size?: 'large' | 'default' | 'small'
    defaultValue?: any
    placeholder?: string
    disabled?: boolean
    allowClear?: boolean
    autofocus?: boolean
    bordered?: boolean
    max?: number
    min?: number
    step?: number
    notFoundContent?: string
    showSearch?: boolean
    maxTagCount?: number
    open?: boolean
    searchValue?: string
    mode?: SelectMode | DateMode
    remoteLoad?: Function
    options?: OptionItem[]
    dropdownClassName?: string
    dropdownStyle?: CSSProperties
    getPopupContainer?: Function
    labelInValue?: boolean
    //input
    // bordered?: boolean
    maxlength?: number
    // textarea
    autosize?: boolean
    showCount?: boolean
    // password
    visibilityToggle?: boolean
    // number
    formatter?: (value: number | string) => string
    parser?: (value: string) => number
    precision?: number
    decimalSeparator?: string
    // radio
    // buttonStyle?: 'outline' | 'solid'
    // rate
    allowHalf?: boolean
    character?: string
    count?: number
    tooltips?: string[]
    // select
    autoClearSearchValue?: boolean
    defaultActiveFirstOption?: boolean
    dropdownMatchSelectWidth?: boolean | number
    filterOption?: boolean | Function
    firstActiveValue?: string | string[]
    maxTagTextLength?: number
    optionFilterProp?: string
    showArrow?: boolean
    tokenSeparators?: string[]
    defaultOpen?: boolean
    // slider
    dots?: boolean
    included?: boolean
    marks?: any
    range?: boolean
    reverse?: boolean
    tipFormatter?: Function
    vertical?: boolean
    tooltipPlacement?: string
    tooltipVisible?: boolean
    getTooltipPopupContainer?: Function
    // switch
    checkedChildren?: string
    unCheckedChildren?: string
    checkedValue?: boolean | string | number
    unCheckedValue?: boolean | string | number
    // cascader
    changeOnSelect?: boolean
    displayRender?: Function
    expandTrigger?: 'click' | 'hover'
    fieldNames?: {
      label?: string
      key?: string
      value?: string
      children?: string
    }
    loadData?: Function
    maxTagPlaceholder?: Function
    placement?: string
    tagRender?: Function
    multiple?: boolean
    locale?: any
    // datePicker & rangePicker & timePicker
    disabledDate?: Function
    disabledTime?: Function
    inputReadOnly?: boolean
    picker?: 'date' | 'week' | 'month' | 'quarter' | 'year'
    popupStyle?: CSSProperties
    valueFormat?: string
    format?: string
    showNow?: boolean
    showTime?: Object | boolean
    showToday?: boolean
    allowEmpty?: boolean
    defaultPickerValue?: any
    ranges?: any
    renderExtraFooter?: Function
    separator?: string
    clearText?: string
    disabledHours?: Function
    disabledMinutes?: Function
    disabledSeconds?: Function
    hideDisabledOptions?: boolean
    hourStep?: number
    minuteStep?: number
    secondStep?: number
    use12Hours?: boolean
    order?: boolean
    // tree-select
    filterTreeNode?: boolean | Function
    listHeight?: number
    treeIcon?: boolean
    showCheckedStrategy?: number
    treeCheckable?: boolean
    treeCheckStrictly?: boolean
    treeData?: TreeItem[]
    replaceFields?: {
      label?: string
      key?: string
      value?: string
      children?: string
    }
    treeDataSimpleMode?: boolean | { id: string; pId: string }[]
    treeDefaultExpandAll?: boolean
    treeDefaultExpandedKeys?: string[] | number[]
    treeLine?: boolean | Object
    treeNodeFilterProp?: string
    treeNodeLabelProp?: string
    virtual?: boolean
    // upload
    accept?: string
    action?: string
    method?: string
    directory?: boolean
    beforeUpload?: Function
    customRequest?: Function
    data?: Object | Function
    headers?: Object
    listType?: 'text' | 'picture' | 'picture-card'
    name?: string
    previewFile?: Function
    showUploadList?: boolean
    supportServerRender?: boolean
    withCredentials?: boolean
    openFileDialogOnClick?: true
  }
  slots?: SlotRenders
  render?: (model: Ref<any>, option: WidgetOptions) => JSX.Element | VNode
}

export interface FormEvent {
  type?: 'primary' | 'danger'
  title: string
  handler: (model: Ref<any>, form: Ref<any>) => any
}

export interface FormEvents {
  [key: string]: FormEvent
}
